package com.web.exiaodao.remote.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.web.exiaodao.business.constant.JConstant;
import com.web.exiaodao.business.entity.*;
import com.web.exiaodao.business.repository.*;
import com.web.exiaodao.remote.service.*;
import com.web.exiaodao.remote.vo.*;
import com.web.webstart.base.constant.XaConstant;
import com.web.webstart.base.exception.BusinessException;
import com.web.webstart.base.service.impl.BaseService;
import com.web.webstart.base.util.XaUtil;
import com.web.webstart.base.util.jpa.DynamicSpecifications;
import com.web.webstart.base.util.jpa.SearchFilter;
import com.web.webstart.base.util.jpa.SearchFilter.Operator;
import com.web.webstart.base.util.jpa.WebUitl;
import com.web.webstart.base.util.result.XaResult;
import org.apache.commons.beanutils.BeanPropertyValueEqualsPredicate;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author: zhangl
 * @times: 2016-11-02 17:35:34
 * 类的说明：前端APIShop接口实现类
 **/
@Service("ApiShopService")
@Transactional(readOnly = false)
public class ApiShopServiceImpl extends BaseService<Shop> implements ApiShopService {

    private static final Logger LOGGER = Logger.getLogger(ApiShopServiceImpl.class);

    @Autowired
    ShopRepository shopRepository;
    @Autowired
    OrderDetailRepository orderDetailRepository;
    @Autowired
    ShopStandardNameRepository standardRespository;

    @Autowired
    ShopStandardValuesRepository standardValuesRespository;

    @Autowired
    ApiShopStandardValuesService shopStandardValuesService;
    @Autowired
    ShopStandardValuesRepository shopStandardValuesRepository;
    @Autowired
    ApiFavoriteTableService favoriteTableService;

    @Autowired
    ApiShopStandardNameService shopStandardNameService;

    @Autowired
    CategoryRepository shopCategoryRepository;

    @Autowired
    ApiCommentService commentService;

    @Override
    public XaResult<ShopVo> findOne(Long tId) throws BusinessException {
        return this.findShopDetail(tId, null);
    }

    @Override
    public XaResult<List<ShopVo>> findListNEStatusByFilter(
            Integer status, Map<String, Object> filterParams, Pageable pageable)
            throws BusinessException {
        Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
        if (status == null) {// 默认显示非删除的所有数据
            status = XaConstant.Status.delete;
        }
        filters.put("status", new SearchFilter("status", Operator.NE, status));
        Page<Shop> page = shopRepository.findAll(DynamicSpecifications
                .bySearchFilter(filters.values(), Shop.class), pageable);
        XaResult<List<ShopVo>> xr = new XaResult<List<ShopVo>>();
        xr.setObject(JSON.parseArray(JSON.toJSONString(page.getContent()), ShopVo.class));
        for (int i = 0; i < page.getContent().size(); i++) {
            xr.getObject().get(i).setId(page.getContent().get(i).getId());
        }
        return xr;
    }

    @Override
    public XaResult<List<ShopVo>> findListEQStatusByFilter(
            Integer status, Map<String, Object> filterParams, Pageable pageable)
            throws BusinessException {
        Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
        if (status == null) {// 默认显示正常数据
            status = XaConstant.Status.valid;
        }
        filters.put("status", new SearchFilter("status", Operator.EQ, status));
        Page<Shop> page = shopRepository.findAll(DynamicSpecifications
                .bySearchFilter(filters.values(), Shop.class), pageable);
        XaResult<List<ShopVo>> xr = new XaResult<List<ShopVo>>();
        xr.setObject(JSON.parseArray(JSON.toJSONString(page.getContent()), ShopVo.class));
        for (int i = 0; i < page.getContent().size(); i++) {
            xr.getObject().get(i).setId(page.getContent().get(i).getId());
        }
        return xr;
    }

    @Override
    public XaResult<ShopVo> multiOperate(String modelIds,
                                         Integer status) throws BusinessException {
        throw new BusinessException(XaConstant.Message.error_method_no_impl);
    }

    @Override
    public XaResult<ShopVo> createModel(Shop model)
            throws BusinessException {
        throw new BusinessException(XaConstant.Message.error_method_no_impl);
    }

    @Override
    public XaResult<ShopVo> updateModel(Shop model)
            throws BusinessException {
        throw new BusinessException(XaConstant.Message.error_method_no_impl);
    }

    @Override
    public XaResult<ShopVo> findShopDetail(Long shopId, Long userId) throws BusinessException {
        Shop obj = shopRepository.findByIdAndStatusNot(shopId, XaConstant.Status.delete);
        XaResult<ShopVo> xr = new XaResult<ShopVo>();
        if (XaUtil.isNotEmpty(obj)) {
            List<ShopStandardName> stands = standardRespository.findByShopIdAndStatusNot(obj.getId().longValue(), XaConstant.Status.delete);

            //设置规格
            ShopVo shopVo = JSON.parseObject(JSON.toJSONString(obj), ShopVo.class);
            if (XaUtil.isNotEmpty(stands)) {
                shopVo = JSON.parseObject(JSON.toJSONString(obj), ShopVo.class);
                List<ShopStandardNameVo> standNames = new ArrayList<>();

                List<ShopStandardValues> values = standardValuesRespository.findByShopIdAndStatusNot(obj.getId(), XaConstant.Status.delete);
                for (int i = 0; i < stands.size(); ++i) {
                    ShopStandardName shopStandardName = stands.get(i);
                    ShopStandardNameVo shopStandardNameVo = JSON.parseObject(JSON.toJSONString(shopStandardName), ShopStandardNameVo.class);
                    ArrayList<ShopStandardValuesVo> shopStandardValuesVos = new ArrayList<>();
                    for (int j = 0; j < values.size(); ++j) {
                        if (shopStandardName.getId().longValue() == (Long.parseLong(values.get(j).getShopStandsNameId()))) {
                            shopStandardValuesVos.add(JSON.parseObject(JSON.toJSONString(values.get(j)), ShopStandardValuesVo.class));
                        }
                    }
                    shopStandardNameVo.setShopStandsValues(shopStandardValuesVos);
                    standNames.add(shopStandardNameVo);
                }
                shopVo.setStandards(standNames);
            }
            //设置分类
            Category category = shopCategoryRepository.findOne(obj.getCategoryType());
            shopVo.setShopCategoryVo(JSON.parseObject(JSON.toJSONString(category), CategoryVo.class));

            //设置是否收藏
            FavoriteTable favo = null;
            if (XaUtil.isNotEmpty(userId)) {
                favo = favoriteTableService.isFavorite(userId, shopId , JConstant.Search_Share_FavType.GOODS+"").getObject();
            }
            shopVo.setFavorite(favo == null ? false : favo.getFavoriteState());
            //设置收藏的id
            shopVo.setFavoriteId(favo == null ? null : favo.getId());

            //查询 前几条 评论
            String sortData2 = "[{property:'createTime',direction:'DESC'}]";
            Pageable pageable2 = WebUitl.buildPageRequest(0, JConstant.COMMENT_TOP_NUM, sortData2);
            Map<String, Object> filterParams2 = WebUitl.getParametersStartingWith(
                    "{'search_EQ_objectId':'"+  shopId +"'" +
                            ",'search_EQ_commentTypes':'"+ JConstant.Order_CommentType.GOODS+"'}", "search_");
            XaResult<Page<CommentVo>> commentsVoXR =  commentService.findListNEStatusByFilterPage(XaConstant.Status.delete, filterParams2,pageable2);
            if (XaUtil.isNotEmpty(commentsVoXR) && XaUtil.isNotEmpty(commentsVoXR.getObject())) {
                shopVo.setCommentVoList(commentsVoXR.getObject());
            }

            //保存点击量
            obj.setClickCont(1 + NumberUtils.toLong(obj.getClickCont()+""));
            shopRepository.save(obj);

            xr.setObject(shopVo);
            xr.getObject().setId(obj.getId());
            LOGGER.info("查询单个实体----->Shop");
        } else {
            xr.error(XaConstant.Message.object_not_find);
            LOGGER.info(XaConstant.Message.object_not_find);
            throw new BusinessException(XaConstant.Message.object_not_find);
        }
        return xr;
    }

    //验证商品信息(1:商品 2:库存 3:规格 4:价格)
    @Override
    public XaResult<Set<Long>> validateShopInfo(List<ShopCarVo> shopCars, boolean isVip) throws BusinessException {
        XaResult<Set<Long>> xr = new XaResult<>();
        Set<Long> shopIdSet = new HashSet<>();//商品id集合
        Map<String, Long> stringLongTreeMap = new TreeMap<>();//商品id和对应库存集合
        Map<String, ShopCarVo> stringShopcarTreeMap = new TreeMap<>();//
        Set<String> standardIdSet = new HashSet<>();//规格id集合
        for (int i = 0; shopCars != null && i < shopCars.size(); ++i) {
            ShopCarVo shopCar = shopCars.get(i);
            shopIdSet.add(shopCar.getShopId());
            stringLongTreeMap.put(shopCar.getShopId().toString(),
                    stringLongTreeMap.containsKey(shopCar.getShopId().toString()) ?
                            shopCar.getCarNumber() + stringLongTreeMap.get(shopCar.getShopId().toString()) :
                            shopCar.getCarNumber());
            stringShopcarTreeMap.put(shopCar.getShopId().toString(), shopCar);
            if (XaUtil.isNotEmpty(shopCar.getStandardIds())) {
                standardIdSet.addAll(Arrays.asList(shopCar.getStandardIds().split(JConstant.SYMBOL_DOT)));
            }
        }
        String shopids = Joiner.on(JConstant.SYMBOL_DOT).join(shopIdSet);//商品ids
        String standardIds = Joiner.on(JConstant.SYMBOL_DOT).join(standardIdSet);//商品规格ids

        List<ShopVo> shopVos = new ArrayList<>();
        Map<String, ShopVo> shopVoMap = new TreeMap<>();//商品id和对应库存集合
        if (XaUtil.isNotEmpty(shopids)) {
            Pageable pageable = WebUitl.buildPageRequest(0, Integer.MAX_VALUE, "[{property:'createTime',direction:'DESC'}]");
            Map<String, Object> filterParams = WebUitl.getParametersStartingWith("{'search_IN_id':'" + JSON.toJSONString(shopIdSet) + "'}", "search_");
            shopVos = this.findListEQStatusByFilter(XaConstant.Status.publish, filterParams, pageable).getObject();
        }
        for (int t = 0; shopVos != null && t < shopVos.size(); ++t) {
            shopVoMap.put(shopVos.get(t).getId().toString(), shopVos.get(t));
        }

        List<ShopStandardValuesVo> standardsVos = new ArrayList<>();
        if (XaUtil.isNotEmpty(standardIds)) {
            Pageable pageable = WebUitl.buildPageRequest(0, Integer.MAX_VALUE, "[{property:'createTime',direction:'DESC'}]");
            Map<String, Object> filterParams = WebUitl.getParametersStartingWith("{'search_IN_shopId':'" + JSON.toJSONString(shopIdSet) + "'}", "search_");
            standardsVos = shopStandardValuesService.findListNEStatusByFilter(XaConstant.Status.delete, filterParams, pageable).getObject();
        }

        if (shopIdSet.size() != shopVos.size()) {
            xr.error("下单商品信息有误!");//商品不存在
            return xr;
        }
        List<Long> standardIdLongs     = com.web.webstart.base.util.CollectionUtils.subCollection(standardsVos, "id");
        List<ShopStandardVo> shopStandardVos = shopStandardNameService.findShopStandsByShopIds(shopIdSet).getObject();

        for (int j = 0; shopCars != null && j < shopCars.size(); ++j) {
            ShopCarVo shopCar = shopCars.get(j);
            if (XaUtil.isEmpty(shopCar.getStandardIds())) {
                continue;
            }
            List<Long> list = Arrays.asList(XaUtil.splitLong(shopCar.getStandardIds(), JConstant.SYMBOL_DOT));
            if (!standardIdLongs.containsAll(list)) {
                xr.error("商品信息和规格不匹配!");
                return xr;
            }
            //找出同一个商品的所有规格
            Collection<ShopStandardVo> subList = CollectionUtils.select(shopStandardVos, new BeanPropertyValueEqualsPredicate("shop_id", shopCar.getShopId()));
            //找出规格nameid的数量
            Map<Long,ShopStandardVo> nameIdmap = com.web.webstart.base.util.CollectionUtils.listToMap(subList.iterator(), new Function<ShopStandardVo, Long>() {
                @Override
                public Long apply(ShopStandardVo shopStandardVo) {
                    return shopStandardVo.getNameId();
                }
            });
            Map<Long,ShopStandardVo> valueIdmap = com.web.webstart.base.util.CollectionUtils.listToMap(subList.iterator(), new Function<ShopStandardVo, Long>() {
                @Override
                public Long apply(ShopStandardVo shopStandardVo) {
                    return shopStandardVo.getValueId();
                }
            });

            Map<Long,ShopStandardVo> filterNameValueMap = new HashMap<>();
            for (int mmm = 0; mmm < list.size(); ++mmm) {
                Long standsValueId = list.get(mmm);
                ShopStandardVo shopStandardVo = valueIdmap.get(standsValueId);
                filterNameValueMap.put(shopStandardVo.getNameId(), shopStandardVo);
            }
            if (filterNameValueMap.size() != nameIdmap.size()) {
                xr.error("商品信息和规格不匹配,请检查!!");
                return xr;
            }
        }
        for (int kk = 0; kk < stringLongTreeMap.keySet().size(); ++kk) {
            String key = stringLongTreeMap.keySet().toArray()[kk] + "";
            Long value = stringLongTreeMap.get(key);
            if (!shopVoMap.containsKey(key)) {
                xr.error("你下单的商品不存在(shop id = " + key + ")");
                return xr;
            }
            if (shopVoMap.get(key).getShopProductInventory() < value) {
                xr.error("库存不足(shop id = " + key + ")");
                return xr;
            }
            double price = isVip ? Double.parseDouble(shopVoMap.get(key).getShopProductPrice()) : Double.parseDouble(shopVoMap.get(key).getOriginalPrice());
            if ( XaUtil.isNotEmpty(stringShopcarTreeMap.get(key).getPrice()) && price != stringShopcarTreeMap.get(key).getPrice().doubleValue()) {
                xr.error("商品价格错误(shop id = " + key + ")");
                return xr;
            }
        }
        xr.setObject(shopIdSet);
        return xr;
    }

    /**
     * 批量,取消订单的时候,归还商品的库存
     * @param orderDetails 该订单号对应的订单详情
     * @return
     * @throws BusinessException
     */
    @Override
    public XaResult<List<Shop>> updateShops(List<OrderDetail> orderDetails) throws BusinessException {
        XaResult<List<Shop>> xr = new XaResult<>();
        if (XaUtil.isEmpty(orderDetails)) {
            return xr;
        }
        Set<String> shopIds  = com.web.webstart.base.util.CollectionUtils.subCollectionSet(orderDetails, "shop_ProductSPU");
        Set<Long>   shopIdss = (Set<Long>) com.web.webstart.base.util.CollectionUtils.transformedCollectionForNumber(shopIds, Long.class);
        //根据shopid获取所有的商品
        List<Shop>  shopList = shopRepository.findByIdInAndStatus(shopIdss, XaConstant.Status.publish);
        //修改所有的商品的库存
        for (int i = 0 ; XaUtil.isNotEmpty(shopList) && i< shopList.size(); ++i) {
            final Shop shop = shopList.get(i);
            List<OrderDetail> fileterOrderDetail = com.web.webstart.base.util.CollectionUtils.filterCopy(orderDetails, new Predicate() {
                @Override
                public boolean evaluate(Object object) {
                    OrderDetail detail = (OrderDetail) object;
                    if (detail.getShop_ProductSPU().equals(shop.getId()+"")) {
                        return true;
                    }
                    return false;
                }
            });
            int count = 0;
            for (int j = 0; fileterOrderDetail != null && j < fileterOrderDetail.size(); ++j) {
                count += fileterOrderDetail.get(j).getProductNum();
            }
            shop.setShopProductInventory(shop.getShopProductInventory() + count);//库存归还
        }
        //进行商品保存
        Iterable<Shop>  shopSaveList = shopRepository.save(shopList);
        xr.setObject(Lists.newArrayList(shopSaveList));
        return xr;
    }
}
